﻿using System;
using LitJson;
using UnityEngine;
using UnityEngine.Networking;
using xuni;

namespace xres
{


    public class GetJsonAction : BaseAsyncAction
    {

        /// <summary>
        /// 网络问题引起的错误(一般可以恢复)
        /// </summary>
        public const string Err_Network = "Err_Network";

        // ++++++++++ 下面的几个错误一般都没法恢复, 一般只能通过玩家联系客服了, 让维护人员去及时排查问题

        /// <summary>
        /// 服务器错误
        /// </summary>
        public const string Err_Http = "Err_Http";

        /// <summary>
        /// 返回数据有问题(比如: 无法解析)
        /// </summary>
        public const string Err_Data = "Err_Data";
        public const string Err_Logic = "Err_Logic";

        // +++++++++

        bool _addTimeStamp;
        string _getUrl = "";
        int _leftRetryCount = 0;
        AsyncOperation _op;

        public JsonData Data { get; internal set; }


        public float CheckProgress()
        {
            switch (_state)
            {
            case BaseAsyncActionState.Init:
                return 0;

            case "Loading":
                return _op.progress;

            }

            return 1;
        }


        public void GetJson(string url, bool addTimeStamp)
        {
            switch (_state)
            {
            case BaseAsyncActionState.Init:
            case BaseAsyncActionState.Finish:
                //可用于重复执行任务
                break;

            default:
                return;
            }

            _state = "Loading";
            _leftRetryCount = 3;
            _addTimeStamp = addTimeStamp;
            _getUrl = url;

            if (false) Debug.Log($"GetJson: url: {url}");
            SendRequest();
        }

        void SendRequest()
        {
            --_leftRetryCount;

            var url = "";
            if (_addTimeStamp)
                url = HttpUtils.AddTimeStamp(_getUrl);
            else
                url = _getUrl;

            var webReq = UnityWebRequest.Get(url);
            webReq.timeout = 2;
            var request = webReq.SendWebRequest();
            _op = request;
            request.completed += OnComplete_HttpGet;
        }

        void OnComplete_HttpGet(AsyncOperation op)
        {
            if (false) Debug.Log($"GetJson: complete");
            _op = null;

            var request = (UnityWebRequestAsyncOperation)op;
            var webReq = request.webRequest;
            using (webReq)
            {
                if (!webReq.isDone || webReq.isNetworkError) //超时或者网络不通
                {
                    if (_leftRetryCount <= 0)
                    {
                        SetError(Err_Network, $"GetJson: timeout and leftRetryCount <= 0, end");
                        Debug.Log(ErrMsg);
                        SetFinishAndNotify(ErrMsg);
                    }
                    else
                    {
                        Debug.Log($"GetJson: timeout, retry: {_leftRetryCount}");
                        SendRequest();
                    }
                }
                else if (webReq.isHttpError || !string.IsNullOrEmpty(webReq.error)) //http错误, 重试没用
                {
                    SetError(Err_Http, $"GetJson: http error, {webReq.error}");
                    Debug.Log(ErrMsg);
                    SetFinishAndNotify(ErrMsg);
                }
                else
                {
                    try
                    {
                        var jsonStr = webReq.downloadHandler.text;
                        if (false) Debug.Log($"GetJson: json: {jsonStr}");

                        var rspJson = JsonMapper.ToObject(jsonStr);
                        if (rspJson.ContainsKey("code"))
                        {
                            var code = (int)rspJson["code"];
                            if (0 == code)
                            {
                                Data = rspJson["data"];
                                SetError("", "");
                                SetFinishAndNotify("");
                            }
                            else //逻辑错误
                            {
                                SetError(Err_Logic, $"GetJson: logic error, {code}");
                                Debug.Log(ErrMsg);
                                SetFinishAndNotify(ErrMsg);
                            }
                        }
                    }
                    catch (Exception ex) //json出错
                    {
                        SetError(Err_Data, $"GetJson: json parse error, {ex.Message}");
                        Debug.Log(ErrMsg);
                        SetFinishAndNotify(ErrMsg);
                    }
                }
            }
        }

    } //end of class


}
